﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Anno.DynamicApi
{
    #region ConditionType
    /// <summary>
    /// 执行者条件类型
    /// </summary>
    public enum ConditionType
    {
        /// <summary>
        /// 并且
        /// </summary>
        AND = 0,
        /// <summary>
        /// 或者
        /// </summary>
        OR = 1,
    }
    #endregion
    #region ConditionFillerType
    /// <summary>
    /// 执行者过滤条件类型
    /// </summary>
    public enum ConditionFillerType
    {
        /// <summary>
        /// 匹配消息头
        /// </summary>
        InputHeader = 0,
        /// <summary>
        /// 匹配入参消息属性
        /// </summary>
        InputProperty = 1,
        /// <summary>
        /// 匹配入参消息体
        /// </summary>
        InputBody = 2,
    }
    #endregion
    #region OperatorType
    /// <summary>
    /// 匹配方式
    /// </summary>
    public enum OperatorType
    {
        /// <summary>
        /// 等于
        /// </summary>
        Equals = 0,
        /// <summary>
        /// 不等于
        /// </summary>
        NotEquals = 1,
        /// <summary>
        /// 包括
        /// </summary>
        Contains = 2,
        /// <summary>
        /// 左匹配
        /// </summary>
        StartsWith = 3,
        /// <summary>
        /// 右匹配
        /// </summary>
        EndsWith = 4,
    }
    #endregion

    /// <summary>
    /// 接口执行者调用条件集合
    /// </summary>
    public class ExecConditions : List<ExecCondition>
    {
        /// <summary>
        /// 执行者条件类型
        /// </summary>
        public virtual ConditionType ConditionType { get; set; } = ConditionType.AND;

        /// <summary>
        /// 是否匹配
        /// </summary>
        /// <param name="input">入参</param>
        /// <returns>是否</returns>
        public virtual bool IsMatch(object input)
        {
            var isMatch = this.Count == 0;
            foreach (var ct in this)
            {
                isMatch = ct.IsMatch(input);
                if (ConditionType == ConditionType.OR && isMatch == true) return isMatch;
                if (ConditionType == ConditionType.AND && isMatch == false) return isMatch;
            }
            return isMatch;
        }

        /// <summary>
        /// 返回JSON对象
        /// </summary>
        public virtual object JObject
        {
            get
            {
                var bJObject = DicAttrs ;

                var execConditions = new System.Collections.Generic.List<object>();
                this.ForEach(ext => execConditions.Add(ext.JObject));
                bJObject["Items"] = execConditions;

                return bJObject;

                //var execConditions = new System.Collections.Generic.List<object>();
                //this.ForEach(ext => execConditions.Add(ext.JObject));
                //return new
                //{
                //    ConditionType= ConditionType.ToString(),
                //    Items= execConditions,
                //};
            }
        }
        public virtual IDictionary<string, object> DicAttrs
        {
            get
            {
                var ret = new System.Dynamic.ExpandoObject();
                IDictionary<string, object> dyret = ret;

                //var execConditions = new System.Collections.Generic.List<IDictionary<string, object>>();
                //this.ForEach(ext => execConditions.Add(ext.DicAttrs));

                dyret["ConditionType"] = ConditionType.ToString();
                //dyret["Items"] = execConditions;

                return ret;
            }
        }
    }

    /// <summary>
    /// 接口执行者调用条件
    /// </summary>
    public class ExecCondition
    {
        /// <summary>
        /// 执行者过滤条件类型
        /// </summary>
        public virtual ConditionFillerType FillerType { get; set; } = ConditionFillerType.InputBody;

        /// <summary>
        /// 匹配方式
        /// </summary>
        public virtual OperatorType Operator { get; set; } = OperatorType.Equals;

        /// <summary>
        /// 匹配路径
        /// </summary>
        public string FiledPath { get; set; }

        /// <summary>
        /// 匹配内容
        /// </summary>
        public string Operand { get; set; }

        /// <summary>
        /// 是否匹配
        /// </summary>
        /// <param name="input">入参</param>
        /// <returns>是否</returns>
        public virtual bool IsMatch(object input)
        {
            var val = getConditionValue(input);
            if (Operator == OperatorType.Equals)
            {
                return Operand == val;
            }
            else if (Operator == OperatorType.NotEquals)
            {
                return Operand != val;
            }
            else if (Operator == OperatorType.Contains)
            {
                return val?.ToLower().Contains(Operand?.ToLower()) == true || Operand?.ToLower().Contains(val?.ToLower()) == true;
            }
            else if (Operator == OperatorType.StartsWith)
            {
                return val?.StartsWith(Operand, StringComparison.OrdinalIgnoreCase) == true || Operand?.StartsWith(val, StringComparison.OrdinalIgnoreCase) == true;
            }
            else if (Operator == OperatorType.EndsWith)
            {
                return val?.EndsWith(Operand, StringComparison.OrdinalIgnoreCase) == true || Operand?.EndsWith(val, StringComparison.OrdinalIgnoreCase) == true;
            }
            return true;
        }

        private string getConditionValue(object input)
        {
            if (FillerType == ConditionFillerType.InputBody)
            {
                return input == null ? "" : input.NullToStr();
            }
            //else if (FillerType == ConditionFillerType.InputHeader)
            //{
            //    return PubFun.GetHeaderValue(FiledPath);
            //}
            else if (FillerType == ConditionFillerType.InputProperty)
            {
                return PubFun.CSScriptCodeInvoke(FiledPath, input).NullToStr();
            }
            return "";
        }

        public ExecCondition() { }
        public ExecCondition(System.Xml.XmlNode xmlNode)
        {
            if (xmlNode == null | xmlNode.NodeType == System.Xml.XmlNodeType.Comment)
            {
                return;
            }
            Init(xmlNode);
        }
		public ExecCondition(Newtonsoft.Json.Linq.JToken xmlNode)
        {
            if (xmlNode == null)
            {
                return;
            }
            Init(xmlNode);
        }
        public void Init(System.Xml.XmlNode conditionNode)
        {
            try
            {
                if (conditionNode == null || conditionNode.NodeType == System.Xml.XmlNodeType.Comment)
                {
                    return;
                }
                FillerType = conditionNode.GetXmlNodeAttributeValue("FillerType", "InputBody").ToEnum_<ConditionFillerType>();
                Operator = conditionNode.GetXmlNodeAttributeValue("Operator", "Equals").ToEnum_<OperatorType>();
                FiledPath = conditionNode.GetXmlNodeAttributeValue("FiledPath");
                Operand = conditionNode.GetXmlNodeAttributeValue("Operand");

            }
            catch { }
        }
        public void Init(Newtonsoft.Json.Linq.JToken conditionNode)
        {
            try
            {
                if (conditionNode == null)
                {
                    return;
                }
                FillerType = conditionNode.GetXmlNodeAttributeValue("FillerType", "InputBody").ToEnum_<ConditionFillerType>();
                Operator = conditionNode.GetXmlNodeAttributeValue("Operator", "Equals").ToEnum_<OperatorType>();
                FiledPath = conditionNode.GetXmlNodeAttributeValue("FiledPath");
                Operand = conditionNode.GetXmlNodeAttributeValue("Operand");
            }
            catch { }
        }

        /// <summary>
        /// 返回JSON对象
        /// </summary>
        public virtual object JObject
        {
            get
            {
                return DicAttrs;
                //return new
                //{
                //    FillerType= FillerType.ToString(),
                //    Operator= Operator.ToString(),
                //    Operand
                //};
            }
        }
        public virtual IDictionary<string, object> DicAttrs
        {
            get
            {
                var ret = new System.Dynamic.ExpandoObject();
                IDictionary<string, object> dyret = ret;

                dyret["FillerType"] = FillerType.ToString();
                dyret["Operator"] = Operator.ToString();
                dyret["FiledPath"] = FiledPath;
                dyret["Operand"] = Operand;

                return ret;
            }
        }
    }
}